﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Security;
using Microsoft.Xrm.Client;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Client.Services;
using System.ServiceModel;
using System.Web.Configuration;
using System.Configuration;
using Microsoft.Xrm.Sdk.Messages;

namespace Applications.Framework.Web.Providers
{
    internal static class CrmCommon
    {
        internal static Guid CreateEntity(Entity entity, CrmConnection connection)
        {
            using (CrmOrganizationServiceContext service = new CrmOrganizationServiceContext(connection))
            {
                Guid id = service.Create(entity);
                entity.Id = id;
                return id;
            }
        }

        internal static void UpdateEntity(Entity entity, CrmConnection connection)
        {
            using (CrmOrganizationServiceContext service = new CrmOrganizationServiceContext(connection))
            {
                service.Update(entity);
            }
        }

        internal static void DeleteEntity(Entity entity, CrmConnection connection)
        {
            connection.Timeout = new TimeSpan(0, 10, 0);
            using (CrmOrganizationServiceContext service = new CrmOrganizationServiceContext(connection))
            {
                try
                {
                    service.Delete(entity.LogicalName, entity.Id);
                }
                catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault> fault)
                {
                    throw fault;
                }

                catch (Exception ex)
                {
                    throw ex;
                }

            }
        }

        internal static EntityCollection RetrieveByFilter(string EntityName, FilterExpression Filter, CrmConnection connection, bool CacheResults = true)
        {
            if (CacheResults)
            {
                using (CrmOrganizationServiceContext service = new CrmOrganizationServiceContext(connection))
                {
                    QueryExpression query = new QueryExpression(EntityName);
                    query.ColumnSet = new ColumnSet(true);
                    query.Criteria = Filter;

                    query.PageInfo = new PagingInfo() { PageNumber = 1, PagingCookie = null, Count = 5000 };
                    EntityCollection ResultCollection = new EntityCollection();
                    while (true)
                    {
                        EntityCollection col = service.RetrieveMultiple(query);
                        ResultCollection.EntityName = col.EntityName;
                        ResultCollection.Entities.AddRange(col.Entities);
                        if (col.MoreRecords)
                        {
                            query.PageInfo.PageNumber++;
                            query.PageInfo.PagingCookie = col.PagingCookie;
                        }
                        else
                        {
                            break;
                        }
                    }
                    return ResultCollection;
                }
            }
            else
            {
                OrganizationService srv = new OrganizationService(connection);
                using (CrmOrganizationServiceContext service = new CrmOrganizationServiceContext(srv))
                {
                    QueryExpression query = new QueryExpression(EntityName);
                    query.ColumnSet = new ColumnSet(true);
                    query.Criteria = Filter;

                    query.PageInfo = new PagingInfo() { PageNumber = 1, PagingCookie = null, Count = 5000 };
                    EntityCollection ResultCollection = new EntityCollection();
                    while (true)
                    {
                        EntityCollection col = service.RetrieveMultiple(query);
                        ResultCollection.EntityName = col.EntityName;
                        ResultCollection.Entities.AddRange(col.Entities);
                        if (col.MoreRecords)
                        {
                            query.PageInfo.PageNumber++;
                            query.PageInfo.PagingCookie = col.PagingCookie;
                        }
                        else
                        {
                            break;
                        }
                    }
                    return ResultCollection;
                }
            }
        }

        internal static EntityCollection GetRelated(Entity PrimaryEntity, string RelatedEntityName, string ForeignKeyField, CrmConnection connection)
        {
            using (CrmOrganizationServiceContext service = new CrmOrganizationServiceContext(connection))
            {
                IQueryable<Entity> query = from entity in service.CreateQuery(RelatedEntityName)
                                           where (Guid)entity[ForeignKeyField] == PrimaryEntity.Id
                                           select entity;

                EntityCollection col = new EntityCollection(query.ToList());
                col.EntityName = RelatedEntityName;
                return col;
            }
        }

        internal static void AddRelated(Entity PrimaryEntity, EntityCollection RelatedEntities, string RelationshipName, CrmConnection connection)
        {
            using (CrmOrganizationServiceContext service = new CrmOrganizationServiceContext(connection))
            {
                EntityReferenceCollection col = new EntityReferenceCollection();
                foreach (Entity ent in RelatedEntities.Entities)
                {
                    col.Add(ent.ToEntityReference());
                }
                AssociateRequest request = new AssociateRequest()
                {
                    Target = PrimaryEntity.ToEntityReference(),
                    RelatedEntities = col,
                    Relationship = new Relationship(RelationshipName)
                };
                AssociateResponse response = (AssociateResponse)service.Execute(request);
            }
        }

        internal static void RemoveRelated(Entity PrimaryEntity, EntityCollection RelatedEntities, string RelationshipName, CrmConnection connection)
        {
            using (CrmOrganizationServiceContext service = new CrmOrganizationServiceContext(connection))
            {
                EntityReferenceCollection col = new EntityReferenceCollection();
                foreach (Entity ent in RelatedEntities.Entities)
                {
                    col.Add(ent.ToEntityReference());
                }
                DisassociateRequest request = new DisassociateRequest()
                {
                    Target = PrimaryEntity.ToEntityReference(),
                    RelatedEntities = col,
                    Relationship = new Relationship(RelationshipName)
                };
                DisassociateResponse response = (DisassociateResponse)service.Execute(request);
            }
        }

    }
}
